GraphQL Operation
操作名 (operation name)
operationName とは以下クエリドキュメントでいうQueryArticlesのこと。中で記述した操作のくくりとして名前をつけられる。基本つけるべき。
ネットワークやサーバーのログに現れるためデバッグしやすい
なにをしたいoperationなのかがわかりやすくなる
code:graphql
query QueryArticles {
articles {
title
}
}
ドキュメント
queryとかmutation、subscriptionではじまるやつ
プログラム実行時に動的に組み立てることは避け、静的な (static) クエリ文字列をそのまま扱うことが望ましい
スキーマとドキュメントからクライアントコードを自動生成できるから
Query
(例え技術的には可能でも)データの作成更新削除は行わないオペレーション
あくまでも、取得
1つのオペレーションの中に複数のqueryを入れたとき、それらは並列に実行される
query内のフィールド名とレスポンスのフィールド名は一致しているべき
code:graphql
リクエスト
{
hero {
name
}
}
レスポンス
{
"data": {
"hero": {
"name": "R2-D2"
}
}
}
Argument
フィールド単位でサーバー側に引数を渡すこともできる
サーバー側はよしなに渡された値をみて処理をカスタムできる
RESTと違って1リクエストで好きなようにやれる
code:graphql
リクエスト
{
human(id: "1000") {
name
height(unit: FOOT)
}
}
レスポンス
{
"data": {
"human": {
"name": "Luke Skywalker",
"height": 5.6430448
}
}
}
Alias
同じフィールドに対して異なる引数を指定したいときは、aliasを使うことでquery内のフィールド名とレスポンスのフィールド名の一致を守れる
code:graphql
リクエスト
{
empireHero: hero(episode: EMPIRE) {
name
}
jediHero: hero(episode: JEDI) {
name
}
}
レスポンス
{
"data": {
"empireHero": {
"name": "Luke Skywalker"
},
"jediHero": {
"name": "R2-D2"
}
}
}
Fragment
フィールド宣言の再利用はfragmentを使うことで実現できる
code:graphql
{
leftComparison: hero(episode: EMPIRE) {
...comparisonFields
}
rightComparison: hero(episode: JEDI) {
...comparisonFields
}
}
fragment comparisonFields on Character {
name
appearsIn
friends {
name
}
}
レスポンス
{
"data": {
"leftComparison": {
"name": "Luke Skywalker",
"appearsIn": [
"NEWHOPE",
"EMPIRE",
"JEDI"
],
"friends": [
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
},
{
"name": "C-3PO"
},
{
"name": "R2-D2"
}
]
},
"rightComparison": {
"name": "R2-D2",
"appearsIn": [
"NEWHOPE",
"EMPIRE",
"JEDI"
],
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
Variables
query ドキュメント内の静的なArgumentを $変数名にする
OperationName指定時に $変数名を受け取るようにする
OperationName ($episode: Episode) のように、$変数名: 型名
型名には、Scalar型、enum、inputObjectが使える
$episode: Episode = JEDI のように初期値を指定できる
別のjsonを使って、変数名: value をquery呼び出し時に渡す
code:graphql
query HeroNameAndFriends($episode: Episode) {
hero(episode: $episode) {
name
friends {
name
}
}
}
// variable
{
"episode": "JEDI"
}
// Response
{
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
Directives
実行時にクエリのフィールドを適用するか否かを制御できる
@include(if: Boolean)
if がtrueのときにフィールドをクエリに含む
@skip(if: Boolean)
if がtrueのときにフィールドをクエリに含まない
code:graphql
query Hero($episode: Episode, $withFriends: Boolean!) {
hero(episode: $episode) {
name
friends @include(if: $withFriends) {
name
}
}
}
{
"episode": "JEDI",
"withFriends": false
}
{
"data": {
"hero": {
"name": "R2-D2"
}
}
}
Inline Fragments
Union型やInterface型を返すフィールドの場合、... 具象型 を指定することで、返ってきたときに具象型単位で欲しいフィールドを指定できる
以下の例ではheroが返すCharacterというUnion型の具体が、Droid型だった場合とHuman型だった場合それぞれで何が欲しいかを指定している
code:graphql
query HeroForEpisode($ep: Episode!) {
hero(episode: $ep) {
name
... on Droid {
primaryFunction
}
... on Human {
height
}
}
}
// variables
{
"ep": "JEDI"
}
// レスポンス
{
"data": {
"hero": {
"name": "R2-D2",
"primaryFunction": "Astromech"
}
}
}
Meta fields
__typename
返却値の型を表示できる
具象型が何だったのかをクライアントが明らかにしたいときに便利
code:graphql
{
search(text: "an") {
__typename
... on Human {
name
}
... on Droid {
name
}
... on Starship {
name
}
}
}
// レスポンス
{
"data": {
"search": [
{
"__typename": "Human",
"name": "Han Solo"
},
{
"__typename": "Human",
"name": "Leia Organa"
},
{
"__typename": "Starship",
"name": "TIE Advanced x1"
}
]
}
}
Mutation
1つのオペレーションの中に複数のmutationを入れたとき、それらは順番に実行される